/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2014-06-04
 * V4.0
 */
package com.jphenix.driver.nodehandler.instancea;

import com.jphenix.share.lang.SString;
import com.jphenix.share.printstream.StringPrintStreamTool;
import com.jphenix.share.util.BaseUtil;
import com.jphenix.standard.docs.ClassInfo;
import com.jphenix.standard.lang.IPrintStream;
import com.jphenix.standard.viewhandler.IViewHandler;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 节点信息类
 * 
 * 2018-07-26 修改了获取节点属性容器对象方法，避免返回的属性容器对象中的值被移除，使xml中原始属性值也丢失
 * 2018-12-05 增加了在其子节点中（不包含子节点的子节点，只在一级子节点中查找）获取指定节点名的第一个子节点
 * 2019-04-29 增加了无结束标签节点名source
 * 2019-07-02 增加了fnnc方法，获取第一个符合条件的子节点，如果不存在，则创建该子节点
 * 2019-08-01 修改了cnm方法，如果节点值为空，也要返回该节点的信息
 * 2019-08-02 增加了ac(节点名,节点文本) 方法，通常用于拼装XML报文
 * 2019-08-03 修改了ac(节点名,节点文本)，完善了识别是否使用cdata文本
 * 
 * @author 刘虻
 * 2009-10-22下午02:56:02
 */
@ClassInfo({"2019-08-03 16:04","节点信息类"})
public class Node implements IViewHandler {
	
	protected ArrayList<IViewHandler> childNodeList = null; //子节点序列
	protected ArrayList<IViewHandler> childDealNodeList = null; //可操作子节点序列
	protected HashMap<String,String> attributeSignMap = null; //属性分隔符容器
	protected HashMap<String,String> attributeMap = null; //属性容器
	protected ArrayList<String> attributeKeyList = null; //属性主键容器
	protected ArrayList<String> singleTagNameList = null; //无内容标签名序列
	protected HashMap<String,String> parameterMap = null; //参数容器
	protected ArrayList<String> propertyList = null; //参数序列
	protected String nodeBodyText = null; //文本内容
	protected String nodeName = null; //节点名
	protected boolean isTextNode = false; //是否为文本节点
	protected boolean isSingleTag = false; //是否为无内容标签
	protected boolean isEmpty = true; //是否为空节点
	protected boolean isParameterNode = false; //是否为参数节点
	protected boolean isCdata = false; //是否为大文本内容
	protected IViewHandler parentNode = null; //父节点对象
	protected boolean isEndTag = false; //是否为节点结束标识
	
	protected String errorMsg = null; //错误信息
	
	protected boolean outAll = true; //是否数据当前html内容
	protected boolean outChild = true; //是否输出当前html标签中的子标签信息
	protected boolean outSelf = false; //是否输出当前标签（不控制当前标签下的子标签）
	protected String dealEncode = null; //操作内编码
	protected boolean isLoop = false; //是否跳过该节点
	//因为HTML中存在无结束标识的标签，比如 <input> <br> 在XML中这是不允许的
	protected boolean xmlStyle = false; //是否为XML格式样式
	
	//是否节点已经处理完毕，比如Script，在解析时已经将节点文本设置完毕
	//该变量只在解析内容时用到
	protected boolean isOver = false; 
	protected String locationInfo = null; //来源信息 
	
	
	/**
	 * 构造函数
	 * 2009-10-22下午02:56:03
	 */
	public Node() {
		super();
	}
	
	/**
	 * 获取无内容标签名序列
	 * @author 刘虻
	 * 2009-10-24下午02:01:30
	 * @return 无内容标签名序列
	 */
	public ArrayList<String> getSingleTagNameList() {
		//dl,dd 节点不是无内容标签
		if(singleTagNameList==null) {
			singleTagNameList =  new ArrayList<String>();
			singleTagNameList.add("area");
			singleTagNameList.add("base");
			singleTagNameList.add("basefont");
			singleTagNameList.add("br");
			singleTagNameList.add("col");
			singleTagNameList.add("frame");
			singleTagNameList.add("img");
			singleTagNameList.add("isindex");
			singleTagNameList.add("link");
			singleTagNameList.add("meta");
			singleTagNameList.add("rt");
			singleTagNameList.add("wbr");
			singleTagNameList.add("input");
			singleTagNameList.add("!doctype");
			singleTagNameList.add("param");  
			singleTagNameList.add("hr");
			singleTagNameList.add("source");
		}
		return singleTagNameList;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-22下午05:32:11
	 */
    @Override
    public IViewHandler addAttributeSign(String key, String sign) {
		getAttributeSignMap().put(key,sign);
		return this;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午01:55:53
	 */
	@Override
    public IViewHandler addChildNode(
			int index, IViewHandler childNode) {
		if(childNode==null) {
			return this;
		}
		isSingleTag = false;
		isEmpty = false;
		childNode.setParentNode(this);
		getChildNodes().add(index,childNode);
		//放入索引
		if (!childNode.isTextNode() && childNode.isOutSelf()) {
			getChildDealNodes().add(childNode);
		}
		return this;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:01:24
	 */
	@Override
    public IViewHandler addChildNode(List<IViewHandler> childNodeList) {
		if (childNodeList!=null) {
			isSingleTag = false;
			isEmpty = false;
			for (Object element:childNodeList) {
				if (element!=null && (element instanceof IViewHandler)) {
					((IViewHandler)element).setParentNode(this);
					addChildNode((IViewHandler)element);
				}
			}
		}
		return this;
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2013-1-5 下午12:08:11
	 */
	@Override
    public IViewHandler getNewChild(String nodeName) {
		//构造一个新的子节点
		IViewHandler cVh = newInstance(false);
		cVh.setNodeName(nodeName);
		return cVh;
	}
	
	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:02:12
	 */
	@Override
    public IViewHandler addChildNode(IViewHandler childNode) {
		if (childNode==null) {
			return this;
		}
		isSingleTag = false;
		isEmpty = false;
		childNode.setParentNode(this);
		getChildNodes().add(childNode);
		//放入索引
		if (!childNode.isTextNode() && childNode.isOutSelf()) {
			getChildDealNodes().add(childNode);
		}
		return this;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:03:31
	 */
	@Override
    public IViewHandler addFirstChildNode(IViewHandler childNode) {
		addChildNode(0,childNode);
		return this;
	}

	/**
	 * 覆盖方法  简称：p()
	 * @author 刘虻
	 * 2009-10-23下午02:04:02
	 */
	@Override
    public IViewHandler addProperty(String property) {
		if(!getPropertyList().contains(property)) {
			getPropertyList().add(property);
		}
		return this;
	}
	
	/**
	 * 判断当前节点是否存在指定参数值
	 * @param property 指定参数值
	 * @return 是否存在指定参数值
	 * 2017年11月14日
	 * @author MBG
	 */
	@Override
    public boolean isp(String property) {
		return getPropertyList().contains(property);
	}
	
	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午01:40:01
	 */
	@Override
    public IViewHandler clear() {
		outAll = true;
		outChild = true;
		outSelf = true;
		isTextNode = false;
		isSingleTag = false;
		nodeName = null;
		nodeBodyText = ""; 
		isEmpty = true;
		isCdata = false;
		isEndTag = false;
		errorMsg = null;
		isLoop = false;
		isOver = false; 
		locationInfo = null;
		isParameterNode = false;
		if(childNodeList!=null) {
			childNodeList.clear();
		}
		if(childDealNodeList!=null) {
			childDealNodeList.clear();
		}
		if(attributeSignMap!=null) {
			attributeSignMap.clear();
		}
		if(attributeMap!=null) {
			attributeMap.clear();
		}
		if(attributeKeyList!=null) {
			attributeKeyList.clear();
		}
		if(parameterMap!=null) {
			parameterMap.clear();
		}
		if(propertyList!=null) {
			propertyList.clear();
		}
		return this;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:04:21
	 */
	@Override
    public String getAttribute(String key) {
		return SString.valueOf(attrMap().get(key));
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:04:41
	 */
	@Override
    public List<String> getAttributeKeyList() {
		if(attributeKeyList==null) {
			attributeKeyList = new ArrayList<String>();
		}
		return attributeKeyList;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:05:32
	 */
	@Override
    @SuppressWarnings("unchecked")
	public Map<String,String> getAttributeMap() {
		return (Map<String,String>)attrMap().clone();
	}
	
	/**
	 * 获取属性容器 全称：getAttributeMap()
	 * @return
	 * 2017年11月20日
	 * @author MBG
	 */
	@Override
    @SuppressWarnings("unchecked")
	public Map<String,String> am(){
		return (Map<String,String>)attrMap().clone();
	}
	
	/**
	 * 内部使用方法，获取属性容器
	 * @return 属性容器
	 * 2018年7月26日
	 * @author MBG
	 */
	protected HashMap<String,String> attrMap(){
		if(attributeMap==null) {
			attributeMap = new HashMap<String,String>();
		}
		return attributeMap;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:05:53
	 */
	@Override
    public String getAttributeSign(String key) {
		return SString.valueOf(getAttributeSignMap().get(key));
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-22下午05:33:02
	 */
	@Override
    public Map<String,String> getAttributeSignMap() {
		if(attributeSignMap==null) {
			attributeSignMap = new HashMap<String,String>();
		}
		return attributeSignMap;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:06:29
	 */
	@Override
    public List<IViewHandler> getChildDealNodes() {
		if(childDealNodeList==null) {
			childDealNodeList = new ArrayList<IViewHandler>();
		}
		return childDealNodeList;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:09:50
	 */
	@Override
    public IViewHandler getChildNode(int index) {
		if (getChildNodes().size()>index && getChildNodes().size()>0) {
			return getChildNodes().get(index);
		}
		return newInstance();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-22下午05:29:14
	 */
	@Override
    public List<IViewHandler> getChildNodes() {
		if(childNodeList==null) {
			childNodeList = new ArrayList<IViewHandler>();
		}
		return childNodeList;
	}

	
	/**
	 * 获取包含指定属性名的子节点（包含子节点的子节点）
	 * @param attributeKey 属性名
	 * @return 子节点序列
	 * 2017年3月31日
	 * @author MBG
	 */
	@Override
    public List<IViewHandler> getChildNodesByAttribute(String attributeKey){
		//构造返回值
		ArrayList<IViewHandler> reArrl = new ArrayList<IViewHandler>();
		if (attributeKey==null 
				|| attributeKey.length()<1) {
			return reArrl;
		}
		if (getNodeName().length()>0 && isOutAll() && hasAttributeKey(attributeKey)) {
			reArrl.add(this);
		}
		if (isOutChild()) {
			//获取当前节点中所有子节点
			List<IViewHandler> childNodes = getChildNodes();
			for (IViewHandler chh:childNodes) {
				if (chh==null) {
					continue;
				}
				reArrl.addAll(chh.getChildNodesByAttribute(attributeKey));
			}
		}
		return reArrl;
	}
	
	
	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:10:25
	 */
	@Override
    public List<IViewHandler> getChildNodesByAttribute(
			String attributeKey,String attributeValue) {
		//构造返回值
		ArrayList<IViewHandler> reArrl = new ArrayList<IViewHandler>();
		if (attributeKey==null 
				|| attributeKey.length()<1 
				|| attributeValue==null) {
			return reArrl;
		}
		if (getNodeName().length()>0 && isOutAll()) {
			//获取当前节点id属性值
			String idValue = getAttribute(attributeKey);
			if (idValue!=null && idValue.equals(attributeValue)) {
				reArrl.add(this);
			}
		}
		if (isOutChild()) {
			//获取当前节点中所有子节点
			List<IViewHandler> childNodes = getChildNodes();
			for (IViewHandler chh:childNodes) {
				if (chh==null) {
					continue;
				}
				reArrl.addAll(chh.getChildNodesByAttribute(attributeKey,attributeValue));
			}
		}
		return reArrl;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:11:15
	 */
	@Override
    public List<IViewHandler> getChildNodesByID(String idValue) {
		return getChildNodesByAttribute(
				IViewHandler.NODE_ATTRIB_ID_KEY,idValue);
	}
	
	
	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-9-17 下午07:02:09
	 */
	@Override
    public List<IViewHandler> cid(String idValue) {
		return getChildNodesByAttribute(
				IViewHandler.NODE_ATTRIB_ID_KEY,idValue);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:11:36
	 */
	@Override
    public List<IViewHandler> getChildNodesByName(String nameValue) {
		return getChildNodesByAttribute(
				IViewHandler.NODE_ATTRIB_NAME_KEY,nameValue);
	}
	
	/**
	 * 递归函数
	 * 获取所有符合节点名称的节点序列
	 * @author 刘虻
	 * 2007-4-18下午02:12:51
	 * @param nodeName 节点名称
	 * @param node 指定节点
	 */
	protected IViewHandler getFirstChildNodeByNodeName(String nodeName,IViewHandler node) {
		if (nodeName==null 
				|| node==null 
				|| !node.isOutAll() 
				|| node.getNodeType()==NODE_TYPE_TEXT) {
			return null;
		}
		//先放入当前节点
		if (node.isOutSelf() 
				&& node.getNodeName()!=null 
				&& nodeName.equalsIgnoreCase(node.getNodeName())) {
			return node;
		}
		if (node.isOutChild()) {
			//获取子节点序列
			List<IViewHandler> childNodes = node.getChildDealNodes();
			IViewHandler res; //返回值
			if(childNodes!=null && childNodes.size()>0) {
				for (IViewHandler childNode:childNodes) {
					if (childNode==null 
							|| !childNode.isOutSelf() ) {
						continue;
					}
					res = getFirstChildNodeByNodeName(nodeName,childNode);
					if(res!=null) {
						return res;
					}
				}
			}
		}
		return null;
	}

	/**
	 * 递归函数
	 * 获取所有符合节点名称的节点序列
	 * @author 刘虻
	 * 2007-4-18下午02:12:51
	 * @param nodeName 节点名称
	 * @param node 指定节点
	 * @param nodeArrl 节点序列
	 */
	protected void getChildNodeByNodeName(
			String nodeName,IViewHandler node,List<IViewHandler> nodeArrl) {
		if (nodeName==null 
				|| node==null 
				|| !node.isOutAll() 
				|| node.getNodeType()==NODE_TYPE_TEXT) {
			return;
		}
		//先放入当前节点
		if (node.isOutSelf() 
				&& node.getNodeName()!=null 
				&& nodeName.equalsIgnoreCase(node.getNodeName())) {
			nodeArrl.add(node);
		}
		if (node.isOutChild()) {
			//获取子节点序列
			List<IViewHandler> childNodes = node.getChildDealNodes();
			if(childNodes!=null && childNodes.size()>0) {
				for (IViewHandler childNode:childNodes) {
					if (childNode==null 
							|| !childNode.isOutSelf() ) {
						continue;
					}
					getChildNodeByNodeName(nodeName,childNode,nodeArrl);
				}
			}
		}
	}
	
	/**
	 * 覆盖方法
	 * 缩写名：cnn
	 * @author 刘虻
	 * 2009-10-23下午02:11:40
	 */
	@Override
    public List<IViewHandler> getChildNodesByNodeName(String nodeName) {
		//构造返回值
		ArrayList<IViewHandler> reNodeArrl = new ArrayList<IViewHandler>();
		//执行获取
		getChildNodeByNodeName(nodeName,this,reNodeArrl);
		return reNodeArrl;
	}
	
	/**
     * 根据节点名获取符合条件的节点序列
     * 全名：getChildNodesByNodeName
     * @param nodeName 节点名
     * @return 符合条件的节点序列
     * 2015年4月17日
     * @author 马宝刚
     */
    @Override
    public List<IViewHandler> cnn(String nodeName) {
        //构造返回值
        ArrayList<IViewHandler> reNodeArrl = new ArrayList<IViewHandler>();
        //执行获取
        getChildNodeByNodeName(nodeName,this,reNodeArrl);
        return reNodeArrl;
    }
    
    /**
     * 返回符合节点名的子节点序列（不包含子节点的子节点）
     * @param nodeName 节点名
     */
    @Override
    public List<IViewHandler> ocnn(String nodeName) {
        //构造返回值
        ArrayList<IViewHandler> reNodeArrl = new ArrayList<IViewHandler>();
        if(nodeName==null || nodeName.length()<1) {
        	return reNodeArrl;
        }
        //返回全部子节点
        List<IViewHandler> cList = getChildDealNodes();
        for(IViewHandler ele:cList) {
        	if(!ele.isOutAll() || !ele.isOutSelf() || !nodeName.equals(ele.nn())) {
        		continue;
        	}
        	reNodeArrl.add(ele);
        }
        return reNodeArrl;
    }

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:12:17
	 */
	@Override
    public List<IViewHandler> getChildNodesByPK(String pkValue) {
		return getChildNodesByAttribute(
				IViewHandler.NODE_ATTRIB_PK_KEY,pkValue);
	}
	
	
	/**
	 * 覆盖方法
	 * 刘虻
	 * 2012-6-21 下午3:45:21
	 */
	@Override
    public List<IViewHandler> cpk(String pkValue) {
		return getChildNodesByAttribute(
				IViewHandler.NODE_ATTRIB_PK_KEY,pkValue);
	}
	
	
	/**
	 * 获取存在指定属性名的节点序列
	 * @param attribName 属性名
	 * @return 节点序列
	 * 2014年12月31日
	 * @author 刘虻
	 */
	@Override
    public List<IViewHandler> getAttribNodes(String attribName) {
        //构造返回值
        ArrayList<IViewHandler> reArrl = new ArrayList<IViewHandler>();
        if (attribName==null 
                || attribName.length()<1) {
            return reArrl;
        }
        if (getNodeName().length()>0 && isOutAll()) {
            if(attrMap().containsKey(attribName)) {
                reArrl.add(this);
            }
        }
        if (isOutChild()) {
            //获取当前节点中所有子节点
            List<IViewHandler> childNodes = getChildNodes();
            for (IViewHandler chh:childNodes) {
                if (chh==null) {
                    continue;
                }
                reArrl.addAll(chh.getAttribNodes(attribName));
            }
        }
        return reArrl;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:12:38
	 */
	@Override
    public String getDealEncode() {
		if (dealEncode==null) {
			//绝大部分程序页面都是UTF-8格式的，除非将框架嵌入了别人的系统中，
			//而别人的系统使用了非UTF-8格式的编码（需要设置编码）
			//嵌入别人系统，这种情况属于特例，故写死为UTF-8
			//dealEncode = System.getProperty("file.encoding");
			dealEncode = "UTF-8";
		}
		return dealEncode;
	}

	/**
	 * 获取第一个非文本节点 缩写：fc();
	 * @author 刘虻
	 * 2007-3-18下午09:36:40
	 * @return 第一个非文本节点
	 * @return 返回当前类实例
	 */
	@Override
    public IViewHandler getFirstChildDealNode() {
		List<IViewHandler> childNodes = getChildDealNodes();
		if (childNodes.size()>0) {
			return childNodes.get(0);
		}
		return newInstance();
	}
	
	/**
	 * 获取第一个非文本节点 全称：getFirstChildDealNode();
	 * @author 刘虻
	 * 2007-3-18下午09:36:40
	 * @return 第一个非文本节点
	 * @return 返回当前类实例
	 */
	@Override
    public IViewHandler fc() {
		List<IViewHandler> childNodes = getChildDealNodes();
		if (childNodes.size()>0) {
			return childNodes.get(0);
		}
		return newInstance();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:13:30
	 */
	@Override
    public IViewHandler getFirstChildNode() {
		return getChildNode(0);
	}

	/**
	 * 覆盖方法 简称：fcna()
	 * @author 刘虻
	 * 2009-10-23下午02:01:10
	 */
	@Override
    public IViewHandler getFirstChildNodeByAttribute(
			String attributeKey,String attributeValue) {
		//获取符合属性值条件的子节点
		IViewHandler res = nativeFirstChildNodeByAttribute(attributeKey,attributeValue);
		if(res==null) {
			return newInstance();
		}
		return res;
	}
	
	/**
	 * 内部递归获取第一个符合属性值条件的节点（该方法会返回空）
	 * @param attributeKey    属性名
	 * @param attributeValue  属性值
	 * @return 符合条件的子节点
	 * 2016年12月14日
	 * @author MBG
	 */
	protected IViewHandler nativeFirstChildNodeByAttribute(
			String attributeKey,String attributeValue) {
		if (attributeKey==null 
				|| attributeKey.length()==0 
				|| attributeValue==null) {
			return null;
		}
		if (getNodeName().length()>0 && isOutAll()) {
			//获取当前节点id属性值
			String idValue = getAttribute(attributeKey);
			if (idValue!=null && idValue.equals(attributeValue)) {
				return this;
			}
		}
		if (isOutChild()) {
			//获取当前节点中所有子节点
			IViewHandler res; //返回值
			List<IViewHandler> childNodes = getChildNodes();
			for (IViewHandler chh:childNodes) {
				if (chh==null) {
					continue;
				}
				res = ((Node)chh).nativeFirstChildNodeByAttribute(attributeKey,attributeValue);
				if(res!=null) {
					return res;
				}
			}
		}
		return null;
	}
	
	
	
	/**
	 * 获取当前节点下第一个符合指定属性值的节点 全称：getFirstChildNodeByAttribute
	 * @param attributeKey
	 * @param attributeValue
	 * @return
	 * 2016年12月14日
	 * @author MBG
	 */
	@Override
    public IViewHandler fcna(String attributeKey, String attributeValue) {
		//获取符合属性值条件的子节点
		IViewHandler res = nativeFirstChildNodeByAttribute(attributeKey,attributeValue);
		if(res==null) {
			return newInstance();
		}
		return res;
	}
	

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:13:56
	 */
	@Override
    public IViewHandler getFirstChildNodeByID(String idValue) {
		return getFirstChildNodeByAttribute(
				IViewHandler.NODE_ATTRIB_ID_KEY,idValue);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:14:08
	 */
	@Override
    public IViewHandler getFirstChildNodeByName(String nameValue) {
		return getFirstChildNodeByAttribute(
				IViewHandler.NODE_ATTRIB_NAME_KEY,nameValue);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:14:22
	 */
	@Override
    public IViewHandler getFirstChildNodeByNodeName(String nodeName) {
    	//递归获取第一个符合条件的值
    	IViewHandler res = getFirstChildNodeByNodeName(nodeName,this);
    	if(res==null) {
    		return newInstance();
    	}
        return res;
	}

	/**
     * 根据节点名获取第一个符合条件的节点对象
     * 是  getFirstChildNodeByNodeName 方法的缩写
     * @param nodeName 节点名
     * @return 第一个符合条件的节点对象
     * 2015年4月17日
     * @author 马宝刚
     */
    @Override
    public IViewHandler fnn(String nodeName) {
    	//递归获取第一个符合条件的值
    	IViewHandler res = getFirstChildNodeByNodeName(nodeName,this);
    	if(res==null) {
    		return newInstance();
    	}
        return res;
    }
    
    
    /**
     * 根据节点名获取第一个符合条件的节点对象
     * 如果不存在符合条件的节点，则在当前节点中创建一个新的子节点
     * @param nodeName 节点名
     * @return         子节点
     * 2019年7月2日
     * @author MBG
     */
    @Override
    public IViewHandler fnnc(String nodeName) {
    	//递归获取第一个符合条件的值
    	IViewHandler res = getFirstChildNodeByNodeName(nodeName,this);
    	if(res==null) {
    		res = newInstance(true);
    		res.nn(nodeName);
    		res.setOutSelf(true);
    		res.setOutChild(true);
    		res.setOutAll(true);
    		if(parentNode==null) {
    			//当前节点是跟节点
    			getFirstChildDealNode().addChildNode(res);
    		}else {
    			addChildNode(res);
    		}
    	}
        return res;
    }
    
    
    
	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:14:35
	 */
	@Override
    public IViewHandler getFirstChildNodeByPK(String pkValue) {
		return getFirstChildNodeByAttribute(
				IViewHandler.NODE_ATTRIB_PK_KEY,pkValue);
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:15:27
	 */
	@Override
    public IViewHandler getLastChildDealNode() {
		//获取所有子节点序列
		List<IViewHandler> childNodes = getChildDealNodes();
		if (childNodes.size()>0) {
			return childNodes.get(childNodes.size()-1);
		}
		return newInstance();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:15:43
	 */
	@Override
    public IViewHandler getLastChildNode() {
		return getChildNode(getChildNodes().size()-1);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:15:59
	 */
	@Override
    public IViewHandler getLastChildNodeByAttribute(
			String attributeKey,String attributeValue) {
		//获取符合属性信息的节点序列
		List<IViewHandler> nodes = 
			getChildNodesByAttribute(attributeKey,attributeValue);
		for(int i=nodes.size()-1;i>-1;i--) {
			//获取指定节点
			NodeHandler reHh = (NodeHandler)nodes.get(i);
			if (reHh==null) {
				continue;
			}
			return reHh;
		}
		return newInstance();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午01:55:16
	 */
	@Override
    public String getNodeBody() {
		//构造输出流
		StringPrintStreamTool spst = new StringPrintStreamTool();
		outHtml(spst,true); //重新拼装HTML内容
		return spst.toString();
	}
	
	/**
	 * 输出节点内容 同getNodeBody
	 * @return
	 * 2017年11月8日
	 * @author MBG
	 */
	@Override
    public String html() {
		return getNodeBody();
	}
	
	/**
	 * 输出节点内容 同getNodeBody
	 * @return
	 * 2017年11月8日
	 * @author MBG
	 */
	@Override
    public String xml() {
		return getNodeBody();
	}
	
    /**
     * 替换转义字符
     * @author 刘虻
     * 2007-1-4下午02:25:46
     * @param str 源字符串
     * @return 替换后的字符串
     */
    protected String fixString(String str) {
    	str = swapString(str,"<","&#60;");
    	str = swapString(str,">","&#62;");
    	str = swapString(str,"\n","<br>");
    	return str;
    }

    
    /**
     * 替换字符串中指定的字符
     * @author 刘虻
     * @param str 要操作的字符串
     * @param fromStr 需要替换的字符串
     * @param toStr 替换成的字符串
     * @return 替换后的字符串
     * 2006-1-5  10:10:04
     */
    protected String swapString(String str,String fromStr,String toStr) {
        //导入参数合法化
        if (str==null) {
            return "";
        }
        String[] strs = splitString(str,fromStr);
        StringBuffer reStr = new StringBuffer();
        if (strs != null && strs.length > 0) {
            for (int i=0;i<strs.length;i++) {
                reStr.append(strs[i]); 
                if (i<strs.length-1) {
                    reStr.append(toStr); 
                }
            }
        }
        return reStr.toString();
    }
    
    
    /**
     * 将字符串按指定字符串分割成数组
     * @author 刘虻
     * @param str 被分割的字符串
     * @param splitStr 指定的字符串
     * @return 分割后的数组
     * 2006-3-15  15:37:36
     */
    protected String[] splitString(String str,String splitStr) {
        if (str==null) {
            return new String[0];
        }
        if (splitStr==null || splitStr.length()==0) {
            return new String[] {str,null};
        }
        ArrayList<String> vect = new ArrayList<String>();
        String strSub = null;
        while(str.indexOf(splitStr) > -1) {
            strSub = str.substring(0,str.indexOf(splitStr));
            vect.add(strSub);
            str = str.substring(strSub.length());

            if (str.length() > splitStr.length()) {
                str = str.substring(splitStr.length());
            }else if (strSub.length()==0) {
                str = "";
                break;
            }
        }
        if (str != null && str.length()>0) {
            vect.add(str);
        }
        String[] strs = new String[vect.size()];
        vect.toArray(strs);
        return strs;
    }
	
	/**
	 * 拼装html内容
	 * @author 刘虻
	 * @param ps 输出流
	 * @param outSelf 是否输出当前标签内容
	 * 2006-10-23下午05:48:25
	 * @return html内容
	 */
	protected void outHtml(IPrintStream ps,boolean outSelf) {
		if (!isOutAll()) {
			return;
		}
		if (errorMsg!=null) {
			ps.append(fixString(errorMsg)); //输出错误信息
			errorMsg = null;
			return;
		}
		if(isTextNode()) {
			if(nodeBodyText!=null && nodeBodyText.length()>0) {
				if(isCdata) {
					ps.append("<![CDATA[").append(nodeBodyText).append("]]>"); //直接输出文本
				}else {
					ps.append(nodeBodyText); //直接输出文本
				}
			}
		}else {
			if("no_active".equals(getNodeName())) {
				setOutSelf(false);
			}
			if(isOutSelf() && outSelf) {
				ps.append("<").append(getNodeName());
				//输出节点参数
				for (String prop:getPropertyList()) {
					if (prop==null || prop.length()<1) {
						continue;
					}
					ps.append(" ").append(prop);
				}
				//输出节点属性
				for (String key:getAttributeKeyList()) {
					if (key==null) {
						continue;
					}
					ps
						.append(" ")
						.append(key)
						.append("=")
						.append(getAttributeSign(key))
						.append(SString.valueOf(attrMap().get(key)))
						.append(getAttributeSign(key));
				}
			}
			if(isSingleTag()) {
				if(isOutSelf() && outSelf) {
					ps.append("/>");
				}
			}else {
				if(isOutSelf() && outSelf) {
					ps.append(">");
				}
				if(isOutChild()) {
					for(IViewHandler cVdh:getChildNodes()) {
						if(cVdh==null) {
							continue;
						}
						cVdh.getNodeBody(ps);
					}
				}
				if(isOutSelf() && outSelf) {
					ps.append("</").append(getNodeName()).append(">");
				}
			}
		}
	}
	
	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午01:54:26
	 */
	@Override
    public IViewHandler getNodeBody(IPrintStream printStream) {
		outHtml(printStream,true);
		return this;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-22下午05:11:56
	 */
	@Override
    public String getNodeName() {
		if(nodeName==null) {
			nodeName = "";
		}
		return nodeName;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:16:48
	 */
	@Override
    public String getNodeText() {
		if(isTextNode()) {
			if(nodeBodyText==null) {
				nodeBodyText = "";
			}
			return nodeBodyText;
		}else if(childDealNodeList==null || childDealNodeList.size()<1) {
			//没有控制节点
			if(childNodeList!=null && childNodeList.size()>0) {
				//并且存在子节点
				
				//先检查子节点中是否存在cdata子文本节点，如果存在，则只输出cdata子文本节点
				for(IViewHandler cvh:childNodeList) {
					if(((Node)cvh).isCdata){
						return cvh.getNodeText();
					}
				}
				//没有CDATA节点，输出全部子文本节点
				//构建输出流
				StringPrintStreamTool spst = new StringPrintStreamTool();
				for(IViewHandler cvh:childNodeList) {
					((Node)cvh).outHtml(spst,false);
				}
				return spst.toString();
			}
		}
		//构建输出流
		StringPrintStreamTool spst = new StringPrintStreamTool();
		outHtml(spst,false); //重新拼装HTML内容 不输出标签内容
		return spst.toString();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:17:31
	 */
	@Override
    public int getNodeType() {
		return isTextNode()?NODE_TYPE_TEXT:NODE_TYPE_DEAL;
	}


	
	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:20:21
	 */
	@Override
    public String getParameter(String key) {
		return SString.valueOf(getParameterMap().get(key));
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:21:19
	 */
	@Override
    public Map<String,String> getParameterMap() {
		IViewHandler bn = getBaseNode();
		if(bn==null) {
			return new HashMap<String,String>();
		}
		if(bn.equals(this)) {
			if(parameterMap==null) {
				parameterMap = new HashMap<String,String>();
			}
			return parameterMap;
		}
		return bn.getParameterMap();
	}

	/**
	 * 覆盖方法 等同于 pn()
	 * @author 刘虻
	 * 2009-10-22下午05:30:52
	 */
	@Override
    public IViewHandler getParentNode() {
		if(parentNode==null) {
			return this;
		}
		return parentNode;
	}
	
	/**
	 * 当前节点的父节点 等同于 getParentNode();
	 * @return 节点的父节点
	 * 2016年1月29日
	 * @author 马宝刚
	 */
	@Override
    public IViewHandler pn() {
        if(parentNode==null) {
            return this;
        }
        return parentNode;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-22下午05:31:20
	 */
	@Override
    public List<String> getPropertyList() {
		if(propertyList==null) {
			propertyList = new ArrayList<String>();
		}
		return propertyList;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:21:44
	 */
	@Override
    public boolean hasAttributeKey(String key) {
		if(key==null) {
			return false;
		}
		return attrMap().containsKey(key);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:22:13
	 */
	@Override
    public boolean hasAttributeValue(String value) {
		if(value==null) {
			return false;
		}
		return attrMap().containsValue(value);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:22:33
	 */
	@Override
    public boolean hasChildNodeByAttribute(
			String attributeKey,String attributeValue) {
		//获取子标签
		List<IViewHandler> childNodeList = 
			getChildNodesByAttribute(attributeKey,attributeValue);
		return childNodeList.size() > 0;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:22:57
	 */
	@Override
    public boolean hasChildNodeByID(String idValue) {
		return hasChildNodeByAttribute(
				IViewHandler.NODE_ATTRIB_ID_KEY,idValue);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:23:16
	 */
	@Override
    public boolean hasChildNodeByName(String nameValue) {
		return hasChildNodeByAttribute(
				IViewHandler.NODE_ATTRIB_NAME_KEY,nameValue);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:23:38
	 */
	@Override
    public boolean hasChildNodeByNodeName(String nodeName) {
		//构造子标签序列
		ArrayList<IViewHandler> nodeList = new ArrayList<IViewHandler>();
		//执行获取
		getChildNodeByNodeName(nodeName,this,nodeList);
		return nodeList.size() > 0;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:23:54
	 */
	@Override
    public boolean hasChildNodeByPK(String pkValue) {
		return hasChildNodeByAttribute(
				IViewHandler.NODE_ATTRIB_PK_KEY,pkValue);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:24:10
	 */
	@Override
    public boolean hasChildNodes() {
		return getChildNodes().size() > 0;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:24:25
	 */
	@Override
    public boolean hasParameter(String key) {
		return getParameterMap().containsKey(key);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:24:43
	 */
	@Override
    public boolean hasProperty(String property) {
		return getPropertyList().contains(property);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:24:55
	 */
	@Override
    public IViewHandler innerText(String textString) {
		//构建子节点
		IViewHandler childNode = newInstance();
		childNode.setNodeText(textString);
		removeChildNodes();
		addChildNode(childNode);
		return this;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:25:13
	 */
	@Override
    public boolean isChildNode(Object childNode) {
		if (childNode==null) {
			return false;
		}
		//获取自节点序列
		List<IViewHandler> cNodeList = getChildNodes();
		if (cNodeList.contains(childNode)) {
			return true;
		}
		for (IViewHandler cNode:cNodeList) {
			if (cNode==null) {
				continue;
			}
			if (cNode.isChildNode(childNode)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:25:31
	 */
	@Override
    public boolean isEmpty() {
		return isEmpty;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:25:39
	 */
	@Override
    public boolean isOutAll() {
		return outAll;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:25:51
	 */
	@Override
    public boolean isOutChild() {
		return outChild;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:26:00
	 */
	@Override
    public boolean isOutSelf() {
		return outSelf;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:26:08
	 */
	@Override
    public boolean isSingleTag() {
		return isSingleTag;
	}
	
	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 下午10:32:00
	 */
	@Override
    public boolean st() {
		return isSingleTag;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-22下午05:10:00
	 */
	@Override
    public boolean isTextNode() {
		return isTextNode;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:26:22
	 */
	@Override
    public boolean isTopNode() {
		return parentNode==null || this.equals(parentNode);
	}

	/**
	 * @deprecated 无用
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:26:38
	 */
	@Override
    public boolean isWarning() {
		return false;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:27:17
	 */
	@Override
    public IViewHandler newInstance() {
		return newInstance(true);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 下午10:29:50
	 */
	@Override
    public IViewHandler n() {
		return newInstance(true);
	}
	
	
	/**
	 * 获取新实例 n(boolean alone)
	 * 刘虻
	 * 2010-9-13 上午10:08:31
	 * @param alone true是否作为单独节点， false返回值是当前节点的子节点 
	 * @returnd 新节点对象
	 */
	@Override
    public IViewHandler newInstance(boolean alone) {
		//构建返回值
		Node node = new Node();
		node.dealEncode = dealEncode;
		node.locationInfo = locationInfo;
		if(!alone) {
			addChildNode(node);
		}
		return node;
	}
	
	/**
	 * 覆盖方法 newInstance(boolean alone)
	 * 刘虻
	 * 2010-9-13 上午10:11:41
	 */
	@Override
    public IViewHandler n(boolean alone) {
		return newInstance(alone);
	}
	
	
	/**
	 * 添加并返回一个新的子节点
	 * 刘虻
	 * 2010-7-7 下午05:39:03
	 * @param nodeName 新的子节点名称
	 * @return 新的子节点
	 */
	@Override
    public IViewHandler addNewChildNode(String nodeName) {
		//构建返回值
		IViewHandler node = newInstance(false);
		if(nodeName!=null) {
			node.setNodeName(nodeName);
		}
		return node;
	}
	
	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:46:26
	 */
	@Override
    public String removeAttribute(String key) {
	       //获取已经移出掉的属性值
        String res = SString.valueOf(attrMap().get(key));
        attrMap().remove(key);
		getAttributeSignMap().remove(key);
		getAttributeKeyList().remove(key);
		return res;
	}
	
	
	/**
	 * 刘虻
	 * 2010-8-5 下午03:26:31
	 * @param key 需要移出的属性主键
	 * @return 移出后的属性值
	 */
	@Override
    public String ra(String key) {
	    //获取已经移出掉的属性值
	    String res = SString.valueOf(attrMap().get(key));
	    attrMap().remove(key);
		getAttributeSignMap().remove(key);
		getAttributeKeyList().remove(key);
		return res;
	}
	
	
	/**
	 * 移除指定属性值中指定的部分 全称：removeAttribute
	 * 注意：属性值不分大小写进行匹配
	 * @param key            指定属性主键
	 * @param value         指定属性值中的部分
	 * @return                  移除后的值
	 * 2017年5月9日
	 * @author MBG
	 */
	@Override
    public String ra(String key, String value) {
		//当前属性值
		String sValue = a(key);
		if(sValue.length()>0) {
			if("class".equalsIgnoreCase(key)) {
				//构建返回值
				StringBuffer reSbf = new StringBuffer();
				//分割的部分值数组
				String[] values = BaseUtil.split(sValue," ","\t","\r","\n");
				for(int i=0;i<values.length;i++) {
					if(values[i].length()<1) {
						continue;
					}
					if(values[i].equalsIgnoreCase(value)) {
						continue;
					}
					if(reSbf.length()>0) {
						reSbf.append(" ");
					}
					reSbf.append(values[i]);
				}
				sValue = reSbf.toString();
			}else if("style".equalsIgnoreCase(key)) {
				//构建返回值
				StringBuffer reSbf = new StringBuffer();
				//分割的部分值数组
				String[] values = BaseUtil.split(sValue,";");
				for(int i=0;i<values.length;i++) {
					values[i] = BaseUtil.trim(values[i]," ","\t","\r","\n");
					if(values[i].length()<1) {
						continue;
					}
					if(values[i].equalsIgnoreCase(value)) {
						continue;
					}
					if(reSbf.length()>0) {
						reSbf.append(";");
					}
					reSbf.append(values[i]);
				}
				sValue = reSbf.toString();
			}else {
				//查找指定位置
				int point = sValue.toLowerCase().indexOf(value.toLowerCase());
				if(point>-1) {
					if(point+value.length()<sValue.length()) {
						if(point>0) {
							sValue = sValue.substring(0,point)+sValue.substring(point+value.length());
						}else {
							sValue = sValue.substring(point+value.length());
						}
					}else {
						if(point>0) {
							sValue = sValue.substring(0,point);
						}else {
							sValue = "";
						}
					}
				}
			}
		}
		a(key,sValue); //设置处理后的属性
		return sValue;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:46:43
	 */
	@Override
    public IViewHandler removeChildNode(int index) {
		//获取准备删除的元素
		IViewHandler vdh = getChildNode(index);
		if(vdh!=null) {
			getChildDealNodes().remove(vdh);
		}
		getChildNodes().remove(index);
		return vdh;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:52:29
	 */
	@Override
    public IViewHandler removeChildNode(IViewHandler childNode) {
		getChildDealNodes().remove(childNode);
		getChildNodes().remove(childNode);
		return this;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:53:25
	 */
	@Override
    public IViewHandler removeChildNodeByID(String idValue) {
		//获取子节点根据节点id
		List<IViewHandler> vdhArrl = getChildNodesByID(idValue);
		if (vdhArrl!=null) {
			for (IViewHandler vdh:vdhArrl) {
				if (vdh==null) {
					continue;
				}
				vdh.getParentNode().removeChildNode(vdh);
				return vdh;
			}
		}
		return n();
	}
	
	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:53:25
	 */
	@Override
    public List<IViewHandler> removeChildNodesByID(String idValue) {
		//构建返回值
		ArrayList<IViewHandler> reList = new ArrayList<IViewHandler>();
		//获取子节点根据节点id
		List<IViewHandler> vdhArrl = getChildNodesByID(idValue);
		if (vdhArrl!=null) {
			for (IViewHandler vdh:vdhArrl) {
				if (vdh==null) {
					continue;
				}
				vdh.getParentNode().removeChildNode(vdh);
				reList.add(vdh);
			}
		}
		return reList;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:54:01
	 */
	@Override
    public List<IViewHandler> removeChildNodesByNodeName(String nodeName) {
		//构建返回值
		ArrayList<IViewHandler> reList = new ArrayList<IViewHandler>();
		//获取子节点根据节点名称
		List<IViewHandler> vdhArrl = getChildNodesByNodeName(nodeName);
		if (vdhArrl!=null) {
			for (IViewHandler vdh:vdhArrl) {
				if (vdh==null) {
					continue;
				}
				vdh.getParentNode().removeChildNode(vdh);
				reList.add(vdh);
			}
		}
		return reList;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午02:54:31
	 */
	@Override
    public List<IViewHandler> removeChildNodeByPK(String pkValue) {
		//构建返回值
		ArrayList<IViewHandler> reList = new ArrayList<IViewHandler>();
		//获取子节点根据节点id
		List<IViewHandler> vdhArrl = getChildNodesByPK(pkValue);
		if (vdhArrl!=null) {
			for (IViewHandler vdh:vdhArrl) {
				if (vdh==null) {
					continue;
				}
				vdh.getParentNode().removeChildNode(vdh);
				reList.add(vdh);
			}
		}
		return reList;
	}

	
	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午03:22:22
	 */
	@Override
    public List<IViewHandler> removeChildNodes() {
		//构建返回值
		ArrayList<IViewHandler> reList = new ArrayList<IViewHandler>();
		if(childNodeList!=null) {
			reList.addAll(childNodeList);
		}
		if(childDealNodeList!=null) {
			reList.addAll(childDealNodeList);
		}
		childNodeList = null;
		childDealNodeList = null;
		return reList;
	}

	
	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午03:22:53
	 */
	@Override
    public IViewHandler removeFirstChildNodeByNodeName(String nodeName) {
		//获取子节点根据节点名称
		List<IViewHandler> vdhArrl = getChildNodesByNodeName(nodeName);
		if (vdhArrl!=null) {
			for (IViewHandler reVdh:vdhArrl) {
				if (reVdh==null) {
					continue;
				}
				reVdh.getParentNode().removeChildNode(reVdh);
				return reVdh;
			}
		}
		return n();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午03:23:07
	 */
	@Override
    public IViewHandler removeLastChildNodeByNodeName(String nodeName) {
		//构建返回值
		IViewHandler vdh = null;
		//获取子节点根据节点名称
		List<IViewHandler> vdhArrl = getChildNodesByNodeName(nodeName);
		if (vdhArrl!=null) {
			int count = vdhArrl.size()-1; //子节点数
			for (int i=count;i>-1;i--) {
				//获取元素
				vdh = vdhArrl.get(i);
				if (vdh==null) {
					continue;
				}
				vdh.getParentNode().removeChildNode(vdh);
				break;
			}
		}
		return vdh;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午03:23:39
	 */
	@Override
    public IViewHandler removeProperty(String property) {
		getPropertyList().remove(property);
		return this;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午03:23:52
	 */
	@Override
    public IViewHandler setAttribute(String key, String value) {
		//进行编码
		if (key!=null) {
			key = key.toLowerCase();
		}
		attrMap().put(key,value);
		if (!getAttributeKeyList().contains(key)) {
			getAttributeKeyList().add(key);
			addAttributeSign(key,"\"");
		}
		return this;
	}
	
	/**
	 * 在原有属性值中增加新的值 全称：addAttribute(key,value);
	 * 注意：需要新增加值的属性主键为class，并且该属性已经存在值
	 *           新增值时，会自动在前面增加一个空格，如果是style会自动
	 *           增加个分号
	 * @param key    指定属性值
	 * @param value 需要添加的属性值
	 * @return  当前节点属性
	 * 2017年5月9日
	 * @author MBG
	 */
	@Override
    public IViewHandler aa(String key, String value) {
		if(key==null || key.length()<1 || value==null || value.length()<1) {
			return this;
		}
		String sValue = a(key); //当前属性值
		if(sValue.length()<1) {
			a(key,value);
		}else {
			if("class".equalsIgnoreCase(key)) {
				//分割成内容块
				String[] values = BaseUtil.split(sValue," ","\t","\r","\n");
				for(int i=0;i<values.length;i++) {
					if(values[i].length()<1) {
						continue;
					}
					if(values[i].equalsIgnoreCase(value)) {
						return this;
					}
				}
				a(key,sValue+";"+value);
			}else if("style".equalsIgnoreCase(key)) {
				//分割成内容块
				String[] values = BaseUtil.split(sValue,";");
				for(int i=0;i<values.length;i++) {
					values[i] = BaseUtil.trim(values[i]," ","\t","\r","\n");
					if(values[i].equalsIgnoreCase(value)) {
						return this;
					}
				}
				a(key,sValue+";"+value);
			}else {
				a(key,sValue+value);
			}
		}
		return this;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午03:24:11
	 */
	@Override
    public IViewHandler setChildNode(IViewHandler childNode) {
		removeChildNodes();
		if(childNode==null) {
			return this;
		}
		isSingleTag = false;
		isEmpty = false;
		childNode.setParentNode(this);
		getChildNodes().add(childNode);
		if(!childNode.isTextNode()) {
			getChildDealNodes().add(childNode);
		}
		return this;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午03:26:02
	 */
	@Override
    public IViewHandler setChildNodes(List<IViewHandler> childNodes) {
		removeChildNodes();
		if(childNodes==null) {
			return this;
		}
		isSingleTag = false;
		for(IViewHandler vdh:childNodes) {
			if(vdh==null) {
				continue;
			}
			vdh.setParentNode(this);
			getChildNodes().add(vdh);
			if(!vdh.isTextNode()) {
				getChildDealNodes().add(vdh);
			}
		}
		return this;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午03:30:12
	 */
	@Override
    public IViewHandler setDealEncode(String dealEncode) {
		this.dealEncode = dealEncode;
		return this;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午03:30:40
	 */
	@Override
    public IViewHandler setNodeCdata(String nodeText) {
		if (nodeText==null || nodeText.length()<1) {
			return this;
		}
		//构建子节点
		NodeHandler chh = (NodeHandler)newInstance();
		chh.setParentNode(this);
		chh.isTextNode = true;
		chh.isCdata = true;
		chh.nodeBodyText = nodeText;
		setChildNode(chh);
		return this;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-22下午05:11:39
	 */
	@Override
    public IViewHandler setNodeName(String nodeName) {
		this.nodeName = nodeName;
		outSelf = true;
		return this;
	}

	
	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午03:31:01
	 */
	@Override
    public IViewHandler setNodeText(String nodeText) {
		if (nodeText==null) {
			nodeText = "";
		}
		//构建子节点
		Node chh = (Node)newInstance();
		chh.setParentNode(this);
		chh.isTextNode = true;
		chh.nodeBodyText = nodeText;
		setChildNode(chh);
		return this;
	}
	
	/**
	 * 设置节点中的文本字符串（非HTML或XML）
	 * @param nodeText  文本内容
	 * @return          当前类实例
	 * 2017年11月8日
	 * @author MBG
	 */
	@Override
    public IViewHandler text(String nodeText) {
		return setNodeText(nodeText);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午03:31:44
	 */
	@Override
    public IViewHandler setNodeType(int nodeType) {
		isTextNode = nodeType == NODE_TYPE_TEXT;
		return this;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午03:31:58
	 */
	@Override
    public IViewHandler setOutAll(boolean outAll) {
		this.outAll = outAll;
		return this;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午03:32:56
	 */
	@Override
    public IViewHandler setOutChild(boolean outChild) {
		this.outChild = outChild;
		return this;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午03:34:18
	 */
	@Override
    public IViewHandler setOutSelf(boolean outSelf) {
		this.outSelf = outSelf;
		return this;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午03:34:27
	 */
	@Override
    public IViewHandler setParentNode(IViewHandler parentNode) {
		this.parentNode = parentNode;
		return this;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午03:34:45
	 */
	@Override
    public IViewHandler setSingleTag(boolean singleTag) {
		this.isSingleTag = singleTag;
		return this;
	}
	
	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 下午10:31:36
	 */
	@Override
    public IViewHandler st(boolean singleTag) {
		this.isSingleTag = singleTag;
		return this;
	}

	/**
	 * @deprecated 无用
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-10-23下午03:35:04
	 */
	@Override
    public IViewHandler setWarning(boolean isWarning) {
		return this;
	}

	
	/**
	 * 内部克隆方法
	 * @author 刘虻
	 * 2009-10-22下午05:26:57
	 * @param node 克隆目标对象
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
    protected void nativeClone(Node node) {
		if(attributeSignMap!=null) {
			node.attributeSignMap = (HashMap)(attributeSignMap).clone();
		}
		if(attributeMap!=null) {
			node.attributeMap = (HashMap)(attributeMap).clone();
		}
		if(attributeKeyList!=null) {
			node.attributeKeyList = 
				(ArrayList)(attributeKeyList).clone();
		}
		node.parameterMap = new HashMap();
		if(parameterMap!=null) {
			node.parameterMap.putAll(parameterMap);
		}
		if(propertyList!=null) {
			node.propertyList = 
				(ArrayList)(propertyList).clone();
		}
		node.nodeBodyText = nodeBodyText;
		node.nodeName = nodeName;
		node.isTextNode = isTextNode;
		node.isSingleTag = isSingleTag;
		node.isEmpty = isEmpty;
		node.isEndTag = isEndTag;
		node.isParameterNode = isParameterNode;
		node.isCdata = isCdata;
		node.errorMsg = errorMsg;
		node.outAll = outAll;
		node.outChild = outChild;
		node.outSelf = outSelf;
		node.dealEncode = dealEncode;
		node.parentNode = parentNode;
		node.isLoop = isLoop;
		node.locationInfo = locationInfo;
		node.xmlStyle = xmlStyle;
		node.childNodeList = new ArrayList();
		node.childDealNodeList = new ArrayList();
		if(childNodeList!=null) {
			try {
                for(int i=0;i<childNodeList.size();i++) {
                    //获取元素
                    IViewHandler element = childNodeList.get(i);
                    if(element==null) {
                        continue;
                    }
                    element = (IViewHandler)element.clone();
                    element.setParentNode(node); //放入新的父类
                    node.childNodeList.add(element);
                    if(!element.isTextNode()) {
                        node.childDealNodeList.add(element);
                    }
                }
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
	}

	
	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2006-11-1上午12:35:03
	 */
	@Override
    public Object clone() throws CloneNotSupportedException {
		//构建克隆对象
		Node node = new Node();
		//执行克隆
		nativeClone(node);
		return node;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-11-5下午03:42:03
	 */
	@Override
    public boolean isXmlStyle() {
		return xmlStyle;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2009-11-5下午03:42:08
	 */
	@Override
    public IViewHandler setXmlStyle(boolean xmlStyle) {
		this.xmlStyle = xmlStyle;
		return this;
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:25:04
	 */
	@Override
    public String a(String key) {
		return getAttribute(key);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:25:28
	 */
	@Override
    public IViewHandler a(String key, String value) {
		return setAttribute(key,value);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:25:40
	 */
	@Override
    public IViewHandler ac(IViewHandler childNode) {
		return addChildNode(childNode);
	}
	
	/**
	 * 构建一个名字为childNodeName的子节点
	 * @param childNodeName 子节点的名字
	 * @return 子节点
	 * 2016年1月29日
	 * @author 马宝刚
	 */
	@Override
    public IViewHandler ac(String childNodeName) {
		//构建子节点
	    IViewHandler cn = newInstance(false);
	    cn.nn(childNodeName);
	    return cn;
	}

	/**
	 * 创建指定节点名的子节点并且设置节点文本（该方法通常用在拼装xml报文）
	 * @param childNodeName 节点名
	 * @param childNodeText 节点文本
	 * @return              注意：返回的是当前节点类实例（不是新增的子节点类实例）
	 * 2019年8月2日
	 * @author MBG
	 */
	@Override
    public IViewHandler ac(String childNodeName, String childNodeText) {
		//构建子节点
		IViewHandler cNode = newInstance(false).nn(childNodeName);
		if(childNodeText!=null) {
			//判断是否需要采用CDATA格式
			if(childNodeText.indexOf("<")>-1 
					|| childNodeText.indexOf(">")>-1 
					|| childNodeText.indexOf("\n")>-1) {
				cNode.cdata(childNodeText);
			}else {
				cNode.setNodeText(childNodeText);
			}
		}
		return this;
	}
	
	
	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:25:50
	 */
	@Override
    public IViewHandler afc(IViewHandler childNode) {
		return addFirstChildNode(childNode);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:26:01
	 */
	@Override
    public List<IViewHandler> c() {
		return getChildNodes();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:26:14
	 */
	@Override
    public IViewHandler cdata(String nodeText) {
		return setNodeCdata(nodeText);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:26:23
	 */
	@Override
    public IViewHandler fcid(String idValue) {
		return getFirstChildNodeByID(idValue);
	}
	
	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:26:39
	 */
	@Override
    public String nn() {
		return getNodeName();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:26:53
	 */
	@Override
    public IViewHandler nn(String name) {
		return setNodeName(name);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:27:06
	 */
	@Override
    public IViewHandler nt(String nodeText) {
		return setNodeText(nodeText);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:27:18
	 */
	@Override
    public String nt() {
		return getNodeText();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:27:29
	 */
	@Override
    public boolean oa() {
		return isOutAll();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:27:36
	 */
	@Override
    public IViewHandler oa(boolean outAll) {
		return setOutAll(outAll);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:27:47
	 */
	@Override
    public boolean oc() {
		return isOutChild();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:27:55
	 */
	@Override
    public IViewHandler oc(boolean ooutChild) {
		return setOutChild(outChild);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:28:35
	 */
	@Override
    public boolean os() {
		return isOutSelf();
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:28:43
	 */
	@Override
    public IViewHandler os(boolean outSelf) {
		return setOutSelf(outSelf);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:28:54
	 */
	@Override
    public IViewHandler p(String property) {
		return addProperty(property);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:29:06
	 */
	@Override
    public IViewHandler rcid(String id) {
		return removeChildNodeByID(id);
	}
	
	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:29:06
	 */
	@Override
    public List<IViewHandler> rcsid(String id) {
		return removeChildNodesByID(id);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 上午10:29:19
	 */
	@Override
    public IViewHandler rp(String property) {
		return removeProperty(property);
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-1 下午10:25:19
	 */
	@Override
    public IViewHandler nc(String nodeName) {
		//构建返回值
		IViewHandler node = newInstance();
		if(nodeName!=null) {
			node.setNodeName(nodeName);
		}
		return node;
	}

	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-8-6 上午10:55:10
	 */
	@Override
    public IViewHandler getBaseNode() {
		//获取父节点
		IViewHandler reNode = getParentNode();
		if(reNode==null || reNode.equals(this)) {
			return this;
		}
		return reNode.getBaseNode();
	}
	
	
	/**
	 * 覆盖方法
	 * 刘虻
	 * 2010-10-28 下午02:42:50
	 */
	@Override
    public IViewHandler cn() {
		try {
			return (IViewHandler)clone();
		}catch(Exception e) {}
		return n();
	}
	
	/**
	 * 覆盖方法
	 * 刘虻
	 * 2012-6-21 下午4:43:10
	 */
	@Override
    public IViewHandler mcid(String idValue) {
		//获取其子节点，并且克隆
		IViewHandler cvh = getFirstChildNodeByID(idValue).cn();
		removeChildNodeByID(idValue);
		return cvh;
	}

	/**
	 * 覆盖方法
	 */
    @Override
    public IViewHandler rna(String srcAttributeName, String objAttributeName) {
        setAttribute(objAttributeName,getAttribute(srcAttributeName));
        removeAttribute(srcAttributeName);
        return n();
    }

    /**
     * 覆盖方法
     */
    @Override
    public IViewHandler cpa(String srcAttributeName, String objAttributeName) {
        setAttribute(objAttributeName,getAttribute(srcAttributeName));
        return this;
    }

	/**
	 * 获取来源信息
	 * @return 来源信息
	 * 2014年7月30日
	 * @author 马宝刚
	 */
	@Override
	public String getLocationInfo() {
		return locationInfo;
	}
	
	
	/**
	 * 覆盖方法
	 */
	@Override
    public String toString() {
	    return getNodeBody();
	}
	
	
	/**
	 * 移除指定属性值的节点 简称：rca
	 * @param attributeName  属性名
	 * @param attributeValue 属性值
	 * @return 被移除的节点序列
	 * 2016年11月23日
	 * @author MBG
	 */
	@Override
    public List<IViewHandler> removeChildNodesByAttribute(String attributeName, String attributeValue){
		return rcsa(attributeName,attributeValue);
	}
	
	
	/**
	 * 移除指定属性值的节点 全称：removeChildNodesByAttribute
	 * @param attributeName  属性名
	 * @param attributeValue 属性值
	 * @return 被移除的节点序列
	 * 2016年11月23日
	 * @author MBG
	 */
	@Override
    public List<IViewHandler> rcsa(String attributeName, String attributeValue){
		//构建返回值
		ArrayList<IViewHandler> reList = new ArrayList<IViewHandler>();
		//获取子节点根据节点id
		List<IViewHandler> vdhArrl = getChildNodesByAttribute(attributeName,attributeValue);
		if (vdhArrl!=null) {
			for (IViewHandler vdh:vdhArrl) {
				if (vdh==null) {
					continue;
				}
				vdh.getParentNode().removeChildNode(vdh);
				reList.add(vdh);
			}
		}
		return reList;
	}
	
	/**
	 * 返回首个节点名为nodeName,并且id值为attrValue的节点 （返回值不为空）
	 * @param nodeName   节点名
	 * @param idValue    id值
	 * @return           首个符合条件的子节点 （返回值不为空）
	 * 2017年10月16日
	 * @author MBG
	 */
	@Override
    public IViewHandler fnn(String nodeName, String idValue) {
		//获取返回值
		IViewHandler reVh = getFirstChildNodeByNodeNameAndAttribute(nodeName,"id",idValue,this);
		if(reVh==null) {
			return newInstance();
		}
		return reVh;
	}
	
	/**
	 * 返回当前节点中，节点名为nodeName,并且属性名为attrName,属性值为attrValue的节点 （返回值不为空）
	 * @param nodeName   当前节点或其子节点
	 * @param attrName   属性名
	 * @param attrValue  属性值
	 * @return           首个符合条件的节点 （返回值不为空）
	 * 2017年10月16日
	 * @author MBG
	 */
	@Override
    public IViewHandler fnn(String nodeName, String attrName, String attrValue) {
		//获取返回值
		IViewHandler reVh = getFirstChildNodeByNodeNameAndAttribute(nodeName,attrName,attrValue,this);
		if(reVh==null) {
			return newInstance();
		}
		return reVh;
	}
	
	
	/**
	 * 返回当前节点中，节点名为nodeName,并且属性名为attrName,属性值为attrValue的节点
	 * （递归函数）（注意：返回值可为空）
	 * @param nodeName   当前节点或其子节点
	 * @param attrName   属性名
	 * @param attrValue  属性值
	 * @param node       当前节点或其子节点
	 * @return           首个符合条件的节点（注意：可为空）
	 * 2017年10月16日
	 * @author MBG
	 */
	protected IViewHandler getFirstChildNodeByNodeNameAndAttribute(
			         String nodeName,String attrName,String attrValue,IViewHandler node) {
		if (nodeName==null 
				|| attrName==null
				|| nodeName.length()<1
				|| attrName.length()<1
				|| node==null 
				|| !node.isOutAll() 
				|| node.getNodeType()==NODE_TYPE_TEXT) {
			return null;
		}
		if(attrValue==null) {
			attrValue = "";
		}
		if (node.isOutSelf() 
				&& node.getNodeName()!=null 
				&& nodeName.equalsIgnoreCase(node.getNodeName())
				&& attrValue.equals(node.getAttribute(attrName))) {
			return node;
		}
		if (node.isOutChild()) {
			//获取子节点序列
			List<IViewHandler> childNodes = node.getChildDealNodes();
			IViewHandler res; //返回值
			if(childNodes!=null && childNodes.size()>0) {
				for (IViewHandler childNode:childNodes) {
					if (childNode==null || !childNode.isOutSelf() ) {
						continue;
					}
					res = getFirstChildNodeByNodeNameAndAttribute(nodeName,attrName,attrValue,childNode);
					if(res!=null) {
						return res;
					}
				}
			}
		}
		return null;
	}
	
	
	/**
	 * 将容器中的信息作为属性信息放入节点中
	 * @param data 数据容器
	 * @return     当前类实例
	 * 2017年11月13日
	 * @author MBG
	 */
	@Override
    public IViewHandler a(Map<String,String> data) {
		if(data==null) {
			return this;
		}
		//数据主键序列
		List<String> keyList = BaseUtil.getMapKeyList(data);
		for(String key:keyList) {
			setAttribute(key,data.get(key));
		}
		return this;
	}
	
	/**
	 * 返回第一个子节点
	 * @return 第一个子节点
	 * 2017年11月13日
	 * @author MBG
	 */
	@Override
    public IViewHandler f() {
		//子节点序列
		List<IViewHandler> cList = getChildDealNodes();
		if(cList.size()<1) {
			return newInstance(true);
		}
		return cList.get(0);
	}
	
	/**
	 * 将子节点名作为key，子节点的text作为值拼装成Map
	 * @return 拼装后的Map
	 * 2018年3月2日
	 * @author MBG
	 */
	@Override
    public Map<String,String> cnm(){
		//构建返回值
		Map<String,String> reMap = new HashMap<String,String>();
		//获取其子节点
		List<IViewHandler> cList = getChildDealNodes();
		for(IViewHandler ele:cList) {
			reMap.put(ele.nn(),ele.nt());
		}
		return reMap;
	}
	
	
    /**
     * 返回符合节点名的子节点序列（不包含子节点的子节点）
     * @param nodeName 节点名
     */
    @Override
    public IViewHandler fonn(String nodeName) {
        if(nodeName==null || nodeName.length()<1) {
        	return newInstance();
        }
        //返回全部子节点
        List<IViewHandler> cList = getChildDealNodes();
        for(IViewHandler ele:cList) {
        	if(!ele.isOutAll() || !ele.isOutSelf() || !nodeName.equals(ele.nn())) {
        		continue;
        	}
        	return ele;
        }
        return newInstance();
    }
}
